home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / retry.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  4.4 KB  |  211 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: retry.c,v 5.2 1992/11/10 08:18:25 panos Exp $" ;
  8.  
  9. #include <sys/time.h>
  10. #include <syslog.h>
  11.  
  12. #include "pset.h"
  13.  
  14. #include "access.h"
  15. #include "config.h"
  16. #include "server.h"
  17. #include "state.h"
  18. #include "connection.h"
  19.  
  20. void msg() ;
  21. void out_of_memory() ;
  22.  
  23. static psi_h iter ;
  24. static bool_int retry_timer_running ;
  25.  
  26.  
  27. /*
  28.  * Attempt to start all servers in the retry table
  29.  */
  30. void server_retry()
  31. {
  32.     register struct server *retry_serp ;
  33.     unsigned servers_started = 0 ;
  34.     char *func = "server_restart" ;
  35.     void cancel_retry() ;
  36.     void stop_retry_timer() ;
  37.     void log_failure() ;
  38.  
  39.     if ( iter == NULL )
  40.     {
  41.         iter = psi_create( ps.rws.retries ) ;
  42.         if ( iter == NULL )
  43.         {
  44.             out_of_memory( func ) ;
  45.             return ;
  46.         }
  47.     }
  48.  
  49.     for ( retry_serp = SERP( psi_start( iter ) ) ; retry_serp != NULL ;
  50.                         retry_serp = SERP( psi_next( iter ) ) )
  51.     {
  52.         register struct service *sp = SERVER_SERVICE( retry_serp ) ;
  53.         connection_s *cp = SERVER_CONNECTION( retry_serp ) ;
  54.  
  55.         /*
  56.          * Drop the retry if access control fails or we have
  57.          * a memory allocation problem
  58.          */
  59.         if ( svc_access_control( sp, cp ) == FAILED ||
  60.                       pset_add( ps.rws.servers, retry_serp ) == NULL )
  61.         {
  62.             cancel_retry( retry_serp ) ;
  63.             psi_remove( iter ) ;
  64.             continue ;
  65.         }
  66.  
  67.         if ( server_start( retry_serp ) == OK )
  68.         {
  69.             servers_started++ ;
  70.             SDATA( sp )->retry_servers-- ;
  71.             psi_remove( iter ) ;
  72.             continue ;
  73.         }
  74.         else
  75.         {
  76.             pset_remove( ps.rws.servers, retry_serp ) ;
  77.             if ( retry_serp->fork_failures >= MAX_FORK_FAILURES )
  78.             {
  79.                 /*
  80.                  * give up retrying
  81.                  */
  82.                 msg( LOG_ERR, func, "service %s: %d consecutive fork failures",
  83.                     CONF( sp )->id, retry_serp->fork_failures ) ;
  84.                 log_failure( AC_FORK, sp, cp ) ;
  85.                 cancel_retry( retry_serp ) ;
  86.                 psi_remove( iter ) ;
  87.                 continue ;
  88.             }
  89.             else
  90.             {
  91.                 if ( debug.on )
  92.                     msg( LOG_DEBUG, func,
  93.                         "fork failed for service %s. Retrying...", CONF( sp )->id ) ;
  94.             }
  95.         }
  96.     }
  97.  
  98.     if ( debug.on )
  99.         msg( LOG_DEBUG, func,
  100.             "%d servers started, %d left to retry",
  101.                 servers_started, pset_count( ps.rws.retries ) ) ;
  102.  
  103.     if ( pset_count( ps.rws.retries ) == 0 )
  104.         stop_retry_timer() ;
  105. }
  106.  
  107.  
  108. /*
  109.  * Schedule a retry by inserting the struct server in the retry table
  110.  * and starting the timer if necessary
  111.  */
  112. status_e schedule_retry( serp )
  113.     struct server *serp ;
  114. {
  115.     void start_retry_timer() ;
  116.     char *func = "schedule_retry" ;
  117.  
  118.     if ( pset_add( ps.rws.retries, serp ) == NULL )
  119.     {
  120.         out_of_memory( func ) ;
  121.         return( FAILED ) ;
  122.     }
  123.     SVC_HOLD( SERVER_SERVICE( serp ) ) ;
  124.     SDATA( SERVER_SERVICE( serp ) )->retry_servers++ ;
  125.     start_retry_timer() ;
  126.     return( OK ) ;
  127. }
  128.  
  129.  
  130. /*
  131.  * This function should not be called for servers that correspond to
  132.  * services not in the service table because server_release will result
  133.  * in releasing all memory associated with the service (since the ref
  134.  * count will drop to 0).
  135.  */
  136. void cancel_retry( serp )
  137.     struct server *serp ;
  138. {
  139.     struct service *sp = SERVER_SERVICE( serp ) ;
  140.  
  141.     conn_free( SERVER_CONNECTION( serp ) ) ;
  142.     SDATA( sp )->retry_servers-- ;
  143.     server_release( serp ) ;
  144. }
  145.  
  146.  
  147.  
  148. /*
  149.  * Cancel all retry attempts for the specified service
  150.  */
  151. void cancel_service_retries( sp )
  152.    register struct service *sp ;
  153. {
  154.    register unsigned u ;
  155.    char *func = "cancel_service_retries" ;
  156.  
  157.    if ( SDATA( sp )->retry_servers == 0 )
  158.       return ;
  159.  
  160.     u = 0 ;
  161.     while ( u < pset_count( ps.rws.retries ) )
  162.     {
  163.         register struct server *serp ;
  164.  
  165.         serp = SERP( pset_pointer( ps.rws.retries, u ) ) ;
  166.         if ( SERVER_SERVICE( serp ) == sp )
  167.         {
  168.             msg( LOG_NOTICE, func,
  169.             "dropping retry attempt for service %s", CONF( sp )->id ) ;
  170.             cancel_retry( serp ) ;
  171.             pset_remove_index( ps.rws.retries, u ) ;
  172.             continue ;
  173.         }
  174.         u++ ;
  175.    }
  176. }
  177.  
  178.  
  179. PRIVATE void start_retry_timer()
  180. {
  181.     /*
  182.      * The retry itimerval is set so that the timer expires every 1 second
  183.      * when it is enabled.
  184.      */
  185.     static struct itimerval itv =
  186.         {
  187.             { RETRY_INTERVAL, 0 },
  188.             { RETRY_INTERVAL, 0 }
  189.         } ;
  190.  
  191.     /*
  192.      * Enable timer if necessary.
  193.      */
  194.     if ( ! retry_timer_running )
  195.         if ( setitimer( ITIMER_REAL, &itv, ITIMERVAL_NULL ) == -1 )
  196.             msg( LOG_ERR, "start_retry_timer", "setitimer: %m" ) ;
  197.         else
  198.             retry_timer_running = TRUE ;
  199. }
  200.  
  201.  
  202. PRIVATE void stop_retry_timer()
  203. {
  204.     if ( retry_timer_running )
  205.     {
  206.         (void) setitimer( ITIMER_REAL, ITIMERVAL_NULL, ITIMERVAL_NULL ) ;
  207.         retry_timer_running = FALSE ;
  208.     }
  209. }
  210.  
  211.